/**
 * 
 */
package soa.security.dao.impl;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.ldaptive.Connection;
import org.ldaptive.Response;
import org.ldaptive.SearchOperation;
import org.ldaptive.SearchRequest;
import org.ldaptive.SearchResult;
import org.ldaptive.control.PagedResultsControl;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.ldap.query.ContainerCriteria;
import org.springframework.ldap.query.SearchScope;
import org.springframework.ldap.support.LdapNameBuilder;
import org.springframework.ldap.support.LdapUtils;
import org.springframework.stereotype.Repository;

import soa.security.dao.PersonDao;
import soa.security.domain.Account;
import soa.security.domain.Person;
import soa.security.query.Convertor;

/**
 * @author Cre.Gu
 *
 */
@Repository
public class PersonDaoImpl extends SpringLdapDaoImpl<Person> implements
		PersonDao {
	@Resource
	private LdapTemplate ldapTemplate;

	@Override
	public void create(Person t) {
		t.setCreateTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
				.format(new Date()));
		ldapTemplate.create(t);
	}

	@Override
	public Person findByDn(String dn) {
		Person o = ldapTemplate.findByDn(LdapNameBuilder.newInstance(dn)
				.build(), Person.class);
		o.setUid(LdapUtils.getStringValue(o.getDn(), o.getDn().size() - 1));
		o.setOrganization(unitBelongs(dn));
		return o;
	}

	@Override
	public Person findByPrimaryKey(String baseDn, String id) {
		try {
			ContainerCriteria query = baseQuery(baseDn, SearchScope.ONELEVEL);
			query.and("uid").is(id);
			return ldapTemplate.searchForObject(query, new BaseContextMapper());
		} catch (Exception e) {
			return null;
		}
	}

	@Override
	public List<Person> allPersons(String baseDn, SearchScope searchScope,
			Map<String, Object> parameters) {
		ContainerCriteria query = baseQuery(baseDn, searchScope);

		buildLikeCriteria(query, parameters, "cname");
		buildLikeCriteria(query, parameters, "IDNumber");
		buildEqualsCriteria(query, parameters, "IDType");
		buildEqualsCriteria(query, parameters, "official", new Convertor() {

			@Override
			public String convert(String orig) {
				if ("true".equalsIgnoreCase(orig))
					return "1";
				return "0";
			}
		});

		return ldapTemplate.search(query, new BaseContextMapper());
	}
	
	@Override
	public Page<Person> allPersons(String baseDn, org.ldaptive.SearchScope searchScope, Map<String, Object> parameters,
			PageRequest pageRequest) throws Exception {
		// TODO Auto-generated method stub
		List<Person> results = new ArrayList<Person>();
		Connection conn = null;
		try {
			conn = pool.getConnection();
			conn.open();

			SearchOperation search = new SearchOperation(conn);

			LdapNameBuilder builder = LdapNameBuilder.newInstance(ldaptiveSupport.getBaseDn());
			if (StringUtils.isNotBlank(baseDn))
				builder.add(baseDn);

			String dn = builder.build().toString();
			
			//拼装过滤条件
			String filter = "";
			String objectclass = "(objectclass=zjtzsw-person)";
			String conditions = "";
			if (parameters != null) {
				//人员姓名
				String[] cname = (String[]) parameters.get("cname");
				if (cname != null && cname.length > 0) {
					if (StringUtils.isNotBlank(cname[0]))
						conditions = conditions + "(cname=*" + cname[0] + "*)";
				}
				
				//证件号码
				String[] IDNumber = (String[]) parameters.get("IDNumber");
				if (IDNumber != null && IDNumber.length > 0) {
					if (StringUtils.isNotBlank(IDNumber[0]))
						conditions = conditions + "(IDNumber=*" + IDNumber[0].toUpperCase() + "*)";
				}
				
				//证件类型
				String[] IDType = (String[]) parameters.get("IDType");
				if (IDType != null && IDType.length > 0) {
					if (StringUtils.isNotBlank(IDType[0]))
						conditions = conditions + "(IDNumber=" + IDType[0] + ")";
				}
				
				//在编
				String[] official = (String[]) parameters.get("official");
				if (official != null && official.length > 0) {
					if (StringUtils.isNotBlank(official[0])){
						String offi = "1";
						if (!"true".equals(official[0])) {
							offi = "0";
						}
						conditions = conditions + "(official=" + offi + ")";
					}
						
				}
				
			}
			filter = "(&" + objectclass + conditions + ")";
			
			System.out.println("ND = " + baseDn);
			System.out.println("filter = " + filter);
			
			//测试使用的
			//filter = "(&(objectclass=zjtzsw-person)(dn=PE0030))";
			
			SearchRequest request = new SearchRequest(dn, filter);
			request.setSearchScope(searchScope);
			request.setSizeLimit(0);

			Response<SearchResult> response = search.execute(request);
			int total = response.getResult().size();

			PagedResultsControl prc = new PagedResultsControl(pageRequest.getPageSize());
			String[] dns = null;

			byte[] cookie = null;
			for (int i = 0; i < pageRequest.getPageNumber() + 1; i++) {

				prc.setCookie(cookie);
				request.setControls(prc);

				response = search.execute(request);
				PagedResultsControl ctl = (PagedResultsControl) response.getControl(PagedResultsControl.OID);

				dns = response.getResult().getEntryDns();

				cookie = ctl.getCookie();
				if (cookie == null)
					break;
			}

			for (String b : dns) {
				results.add(findByDn(ldaptiveSupport.wrap4Spring(b)));
			}

			return new PageImpl(results, pageRequest, total);
		} catch (Exception e) {
			throw e;
		} finally {
			if (conn != null)
				conn.close();
		}
	}

	@Override
	public String getObjectClass() {
		return "zjtzsw-person";
	}
	
	@Override
	public List<Person> findByOrgAndName(String baseDn, SearchScope searchScope, String cname) {
		// TODO Auto-generated method stub
		ContainerCriteria query = baseQuery(baseDn, searchScope);

		query.and("cname").is(cname);

		return ldapTemplate.search(query, new BaseContextMapper());
	}
	
}
